use std::{fs::File, io::{BufRead, BufReader}};

// 计算校验码
fn checksum(numbers: &Vec<u32>) -> bool {
    let mut sum = 0;
    for (id, num) in numbers.iter().rev().enumerate() {
        sum += num * ((1 << id) % 11);
    }
    if sum % 11 == 1 {
        true
    } else {
        false
    }
}

// 获得行政区划
fn region(id: &str) -> Option<String> {
    let file = File::open("id2region.txt").unwrap();
    let reader = BufReader::new(file);

    for line in reader.lines() {
        let line = line.unwrap();
        let parts: Vec<&str> = line.split("|    ").collect();
        if parts[0] == id {
            return Some(parts[1].split(" ").collect::<Vec<&str>>().join("-"));
        }
    }
    None
}

// 一代身份证校验
fn check_1st(id_card_no: &str) -> String {
    let mut answer = vec!["身份证号码正确".to_string()];

    // 确定男女
    if let Ok(digit) = id_card_no[14..15].parse::<u32>() {
        if digit % 2 == 0 {
            answer.push("女".to_string());
        } else {
            answer.push("男".to_string());
        }
    } else {
        return "身份证号码错误".to_string();
    }

    // 确定出生日期
    let mut birth = String::new();
    if let Ok(_) = id_card_no[6..8].parse::<u32>() {
        birth.push_str("19");
        birth.push_str(&id_card_no[6..8]);
        birth.push_str("年");
    } else {
        return "身份证号码错误".to_string();
    }

    let month;

    if let Ok(digit) = id_card_no[8..10].parse::<u32>() {
        if digit > 12 || digit < 1 {
            return "身份证号码错误".to_string();
        }
        month = digit;
        birth.push_str(&id_card_no[8..10]);
        birth.push_str("月");
    } else {
        return "身份证号码错误".to_string();
    }

    let days_per_month = vec![31,28,31,30,31,30,31,31,30,31,30,31];
    if let Ok(digit) = id_card_no[10..12].parse::<u32>() {
        if digit > days_per_month[month as usize] || digit < 1 {
            return "身份证号码错误".to_string();
        }
        birth.push_str(&id_card_no[10..12]);
        birth.push_str("日");
    }
    answer.push(birth);
    
    // 确定行政区划
    if let Some(region) = region(&id_card_no[..6]) {
        answer.push(region);
    } else {
        return "身份证号码错误".to_string();
    }
    answer.join(",")
}

// 二代身份证校验
fn check_2nd(id_card_no: &str) -> String {
    let mut numbers = Vec::new();
    let mut answer = Vec::new();

    for ch in id_card_no[..id_card_no.len()-1].chars() {
        if let Some(num) = ch.to_digit(10) {
            numbers.push(num);
        } else {
            return "身份证号码错误".to_string();
        }
    }

    if let Some(ch) = id_card_no.chars().last(){
        if let Some(num) = ch.to_digit(10) {
            numbers.push(num);
        } else {
            if ch == 'X' {
                numbers.push(10);
            } else {
                return "身份证号码错误".to_string();
            }
        }
    }

    if !checksum(&numbers) {
        return "身份证号码错误".to_string();
    } else {
        answer.push("身份证号码正确".to_string());
    }

    // 确定男女
    if numbers[16] % 2 == 0 {
        answer.push("女".to_string());
    } else {
        answer.push("男".to_string());
    }

    // 确定出生日期
    let mut birth = String::new();
    if let Ok(_) = id_card_no[6..10].parse::<u32>() {
        birth.push_str(&id_card_no[6..10]);
        birth.push_str("年");
    } else {
        return "身份证号码错误".to_string();
    }

    let month;

    if let Ok(digit) = id_card_no[10..12].parse::<u32>() {
        if digit > 12 || digit < 1 {
            return "身份证号码错误".to_string();
        }
        month = digit;
        birth.push_str(&id_card_no[10..12]);
        birth.push_str("月");
    } else {
        return "身份证号码错误".to_string();
    }

    let days_per_month = vec![31,28,31,30,31,30,31,31,30,31,30,31];
    if let Ok(digit) = id_card_no[12..14].parse::<u32>() {
        if digit > days_per_month[month as usize] || digit < 1 {
            return "身份证号码错误".to_string();
        }
        birth.push_str(&id_card_no[12..14]);
        birth.push_str("日");
    }
    answer.push(birth);
    
    // 确定行政区划
    if let Some(region) = region(&id_card_no[..6]) {
        answer.push(region);
    } else {
        return "身份证号码错误".to_string();
    }
    answer.join(",")
}

pub fn check_id_card(id_card_no: &str) -> String {
    if id_card_no.len() == 18 {
        check_2nd(id_card_no)
    } else if id_card_no.len() == 15 {
        check_1st(id_card_no)
    } else {
        "身份证号码错误".to_string()
    }
}
